home *** CD-ROM | disk | FTP | other *** search
/ Aminet 41 / Aminet 41 (2001)(Schatztruhe)[!][Feb 2001].iso / Aminet / dev / c / libiconv_src.lha / src / iso2022_jp.h < prev    next >
Encoding:
C/C++ Source or Header  |  2000-11-07  |  4.2 KB  |  194 lines

  1.  
  2. /*
  3.  * ISO-2022-JP
  4.  */
  5.  
  6. /* Specification: RFC 1468 */
  7.  
  8. #define ESC 0x1b
  9.  
  10. /*
  11.  * The state can be one of the following values.
  12.  */
  13. #define STATE_ASCII          0
  14. #define STATE_JISX0201ROMAN  1
  15. #define STATE_JISX0208       2
  16.  
  17. static int
  18. iso2022_jp_mbtowc (conv_t conv, wchar_t *pwc, const unsigned char *s, int n)
  19. {
  20.   state_t state = conv->istate;
  21.   int count = 0;
  22.   unsigned char c;
  23.   for (;;) {
  24.     c = *s;
  25.     if (c == ESC) {
  26.       if (n < count+3)
  27.         goto none;
  28.       if (s[1] == '(') {
  29.         if (s[2] == 'B') {
  30.           state = STATE_ASCII;
  31.           s += 3; count += 3;
  32.           if (n < count+1)
  33.             goto none;
  34.           continue;
  35.         }
  36.         if (s[2] == 'J') {
  37.           state = STATE_JISX0201ROMAN;
  38.           s += 3; count += 3;
  39.           if (n < count+1)
  40.             goto none;
  41.           continue;
  42.         }
  43.         return RET_ILSEQ;
  44.       }
  45.       if (s[1] == '$') {
  46.         if (s[2] == '@' || s[2] == 'B') {
  47.           /* We don't distinguish JIS X 0208-1978 and JIS X 0208-1983. */
  48.           state = STATE_JISX0208;
  49.           s += 3; count += 3;
  50.           if (n < count+1)
  51.             goto none;
  52.           continue;
  53.         }
  54.         return RET_ILSEQ;
  55.       }
  56.       return RET_ILSEQ;
  57.     }
  58.     break;
  59.   }
  60.   switch (state) {
  61.     case STATE_ASCII:
  62.       if (c < 0x80) {
  63.         int ret = ascii_mbtowc(conv,pwc,s,1);
  64.         if (ret == RET_ILSEQ)
  65.           return RET_ILSEQ;
  66.         if (ret != 1) abort();
  67.         conv->istate = state;
  68.         return count+1;
  69.       } else
  70.         return RET_ILSEQ;
  71.     case STATE_JISX0201ROMAN:
  72.       if (c < 0x80) {
  73.         int ret = jisx0201_mbtowc(conv,pwc,s,1);
  74.         if (ret == RET_ILSEQ)
  75.           return RET_ILSEQ;
  76.         if (ret != 1) abort();
  77.         conv->istate = state;
  78.         return count+1;
  79.       } else
  80.         return RET_ILSEQ;
  81.     case STATE_JISX0208:
  82.       if (n < count+2)
  83.         goto none;
  84.       if (s[0] < 0x80 && s[1] < 0x80) {
  85.         int ret = jisx0208_mbtowc(conv,pwc,s,2);
  86.         if (ret == RET_ILSEQ)
  87.           return RET_ILSEQ;
  88.         if (ret != 2) abort();
  89.         conv->istate = state;
  90.         return count+2;
  91.       } else
  92.         return RET_ILSEQ;
  93.     default: abort();
  94.   }
  95.  
  96. none:
  97.   conv->istate = state;
  98.   return RET_TOOFEW(count);
  99. }
  100.  
  101. static int
  102. iso2022_jp_wctomb (conv_t conv, unsigned char *r, wchar_t wc, int n)
  103. {
  104.   state_t state = conv->ostate;
  105.   unsigned char buf[2];
  106.   int ret;
  107.  
  108.   /* Try ASCII. */
  109.   ret = ascii_wctomb(conv,buf,wc,1);
  110.   if (ret != RET_ILSEQ) {
  111.     if (ret != 1) abort();
  112.     if (buf[0] < 0x80) {
  113.       int count = (state == STATE_ASCII ? 1 : 4);
  114.       if (n < count)
  115.         return RET_TOOSMALL;
  116.       if (state != STATE_ASCII) {
  117.         r[0] = ESC;
  118.         r[1] = '(';
  119.         r[2] = 'B';
  120.         r += 3;
  121.         state = STATE_ASCII;
  122.       }
  123.       r[0] = buf[0];
  124.       conv->ostate = state;
  125.       return count;
  126.     }
  127.   }
  128.  
  129.   /* Try JIS X 0201-1976 Roman. */
  130.   ret = jisx0201_wctomb(conv,buf,wc,1);
  131.   if (ret != RET_ILSEQ) {
  132.     if (ret != 1) abort();
  133.     if (buf[0] < 0x80) {
  134.       int count = (state == STATE_JISX0201ROMAN ? 1 : 4);
  135.       if (n < count)
  136.         return RET_TOOSMALL;
  137.       if (state != STATE_JISX0201ROMAN) {
  138.         r[0] = ESC;
  139.         r[1] = '(';
  140.         r[2] = 'J';
  141.         r += 3;
  142.         state = STATE_JISX0201ROMAN;
  143.       }
  144.       r[0] = buf[0];
  145.       conv->ostate = state;
  146.       return count;
  147.     }
  148.   }
  149.  
  150.   /* Try JIS X 0208-1990 in place of JIS X 0208-1978 and JIS X 0208-1983. */
  151.   ret = jisx0208_wctomb(conv,buf,wc,2);
  152.   if (ret != RET_ILSEQ) {
  153.     if (ret != 2) abort();
  154.     if (buf[0] < 0x80 && buf[1] < 0x80) {
  155.       int count = (state == STATE_JISX0208 ? 2 : 5);
  156.       if (n < count)
  157.         return RET_TOOSMALL;
  158.       if (state != STATE_JISX0208) {
  159.         r[0] = ESC;
  160.         r[1] = '$';
  161.         r[2] = 'B';
  162.         r += 3;
  163.         state = STATE_JISX0208;
  164.       }
  165.       r[0] = buf[0];
  166.       r[1] = buf[1];
  167.       conv->ostate = state;
  168.       return count;
  169.     }
  170.   }
  171.  
  172.   return RET_ILSEQ;
  173. }
  174.  
  175. static int
  176. iso2022_jp_reset (conv_t conv, unsigned char *r, int n)
  177. {
  178.   state_t state = conv->ostate;
  179.   if (state != STATE_ASCII) {
  180.     if (n < 3)
  181.       return RET_TOOSMALL;
  182.     r[0] = ESC;
  183.     r[1] = '(';
  184.     r[2] = 'B';
  185.     /* conv->ostate = 0; will be done by the caller */
  186.     return 3;
  187.   } else
  188.     return 0;
  189. }
  190.  
  191. #undef STATE_JISX0208
  192. #undef STATE_JISX0201ROMAN
  193. #undef STATE_ASCII
  194.